const MAX_POINT:u32 = 10_000;

fn main() {
    println!("Hello, world!");
    // 变量
    println!("The const is {}", MAX_POINT);

    let spaces = "   ";
    let spaces = spaces.len();

    println!("长度为 {}", spaces);

    // 3.2 数据类型
    // Rust 是静态编译语言，在编译时必须知道所有变量的类型：
    // - 基于使用的值，编译器通常能够推断出它的具体类型
    // - 但如果可能的类型比较多（例如把 String 转为整数的 parse 方法），就必须添加类型的标注，否则编译会报错
    let guess:u32 = "42".parse().expect("Not a number");
    println!("转换为 {}", guess);
    // 3.2.1 整数类型
    // · 整数类型没有小数部分
    // · 例如 u32 就是一个无符号的整数类型，占据 32 位的空间
    // · 无符号整数类型以 u 开头
    // · 有符号整数类型以 i 开头
    // Rust 的整数类型列表如下：
    // Length       Signed      Unsigned
    // 8-bit        i8          u8
    // 16-bit       i16         u16
    // 32-bit       i32         u32
    // 64-bit       i64         u64
    // 128-bit      i128        u128
    // arch         isize       usize
    // 每种都分 i 和 u，以及固定的位数
    // 有符号范围：-(2^n - 1) 到 2^n -1
    // 无符号范围：0 到 2^n - 1
    // isize 和 usize 类型由计算机架构决定，如果是 64 位计算机则为 64 位，如果是 32 位计算机则为 32 位
    // 使用 isize 和 usize 的主要场景是对某种集合进行索引操作。
    // 3.2.2 整数字面值
    // Number literials     Example
    // Decimal              98_222
    // Hex                  0xff
    // Octal                0077
    // Binary               0b1111_0000
    // Byte(u8 only)        b'A'
    // 除了 byte 类型外，所有的数值字面值都允许使用类型后缀：如 57u8
    // 如果你不太清楚应该使用哪种类型，可以使用 Rust 相应的默认类型，如整数默认类型是 i32，其总体上来说速度很快，即使在 64 位操作系统中
    // 3.2.3 整数溢出
    // 如，u8 的范围是 0-255，如果你把一个 u8 变量的值设为 256，那么
    // - 调试模式下编译时，Rust 会检查整数溢出，如果发生溢出，程序在运行时就会 panic
    // - 发布模式下（--release）编译时，Rust 不会检查可能导致 panic 的整数溢出
    //      · 如果溢出发生，Rust 会执行“环绕”操作：256 变为 0，257 变为 1...，但程序不会 panic
    // 3.2.3 浮点类型
    // · Rust 有两种基础的浮点类型：
    //      - f32，32位，单精度
    //      - f64，64位，双精度
    // · Rust 的浮点类型使用 IEEE-754 标准来表述
    // · f64 是默认类型，因为现代 CPU 上 f64 和 f32 的速度差不多，而且精度更高。
    let x = 2.0; // f64
    let y:f32 = 3.0; // f32
    // 3.3 数值操作
    // 加减乘除余
    let sum = 5 + 10;
    let difference = 95.5 - 4.3;
    let product = 4 * 30;
    let quotient = 56.7 / 32.2;
    let reminder = 54 % 5;
    // 3.3.1 布尔类型
    // 布尔类型有两个值：true 和 false
    // 占用一个字节大小，符号为 bool
    let t = true;
    let f: bool = false;
    // 3.3.2 字符类型
    // · Rust 语言中 char 类型被用来描述语言中最基础的单个字符
    // · 字符类型的字面值使用单引号
    // · 占用 4 字节大小
    // · 是 Unicode 标量值，可以表示比 ASC 多得多的字符内容：拼音、中日韩文、零长度空白字符、emoji等。Unicode 取值范围：
    //      - U+0000 到 U+D7FF
    //      - U+E000 到 U+10FFFF
    // 但 Unicode 中并没有“字符”的概念，所以直觉上认为的字符也许与 Rust 中的概念并不相符
    let x1 = 'z'; // 英语
    let y1: char = 'ê'; // 法语
    let z1 = '😀'; // emoji
    println!("emoji {}", y1);
    println!("emoji {}", z1);
    // 3.4 复合类型
    // 3.4.1 复合类型可以将多个值放在一个类型里。
    // Rust 提供了两种基础的复合类型：元组（Tuple）、数组
    // 3.4.2 Tuple
    // ·可以将多个类型的多个值放在一个类型中
    // ·Tuple的长度是固定的：一旦声明就无法改变
    // 3.4.2.1 创建 Tuple
    // 在小括号里，将值用逗号隔开
    // Tuple 中的每个位置都对应一个类型，Tuple 中各元素的类型不必相同，获取变量可以使用点标记法，即 Tuple 变量名后面接点和索引号，索引号以 0 开始
    let tup:(i32, f64, u8) = (500, 6.4, 1);
    println!("{}, {}, {}", tup.0, tup.1, tup.2);
    // 可以使用模式匹配解构（destructure）Tuple 来获取元素的值
    let (x3, y3, z3) = tup;
    println!("{}, {}, {}", x3, y3, z3);
    // 3.4.3 数组
    // 声明一个数组即在中括号里，各值以逗号隔开
    // 如果想让你的数据保存在栈（stack）中，而不是在堆（heap）中，或者想保证有固定数量的元素，这时使用数组较好
    // 数组没有 vector 灵活，vector 和 数组类似，它由标准库提供，它的长度可变
    let a = [1, 2, 3];
    // 3.4.3.1 数组的类型
    // 数组的类型形式：[类型;长度]，如下：
    let array:[i32;5] = [1,2,3,4,5];
    // 另一种声明数组的方法
    // 如果数组中的每个元素值都相同，那么：
    // · 在中括号中指定初始值
    // · 然后是个“;”
    // · 最后是数组长度
    // 如：
    let array1 = [0;5]; // 相当于：let a = [0,0,0,0,0];
    // 3.4.3.2 数组元素访问
    // 使用索引来访问
    // 如果索引超出范围那么：
    // · 编译会通过
    // · 运行会报错（panic）：Rust不允许其继续访问相应地址的内存
    let element1 = array[0];
}
